<?php

namespace System\Loader;

/**
 * 类库装载类
 * 
 * @package Dream
 * @subpackage ClassAlias
 * @namespace System\Loader
 * @author lewis (lewisld@yeah.net)
 */
class ClassLoader
{

    /**
     * 所有加载的类库文件列表
     * 
     * @static
     *
     * @access protected
     * @var array
     */
    protected static $loadFileList = [];

    /**
     * 注册类库的自动装载方法
     * 
     * @static
     *
     * @access public
     * @param string $prepend 被注册的自动装载方法是否添加至列队至首，默认 “false” = 否
     * @return void 没有返回值
     */
    public static function register($prepend = FALSE)
    {
        spl_autoload_register([
            self,
            'loadClass'
        ], TRUE, $prepend);
    }

    /**
     * 卸载类库的自动装载方法
     * 
     * @static
     *
     * @access public
     * @return void 没有返回值
     */
    public static function unregister()
    {
        spl_autoload_unregister([
            self,
            'loadClass'
        ]);
    }

    /**
     * 类的自动加载方法 当使用一个类而这个类又不存在时系统就会自动通过此方法加载类文件
     * 
     * @static
     *
     * @access public
     * @param string $class 类名
     * @return boolean 类库加载成功返回 “true”，否则返回 “false”
     */
    public static function loadClass($class)
    {
        if (! isset(self::$loadFileList[$class])) { // 类文件没有装载过
            $file = self::findFile($class);
            if (self::load($file)) { // 类文件引入成功
                if (! class_exists($class)) {
                    return FALSE;
                } // 如果类未定义返回 “false”
                self::$loadFileList[$class] = $file; // 设置类以装载
                self::initclass($class); // 初始化类
                unset($file);
                
                return TRUE;
            }
        }
        
        return FALSE;
    }

    /**
     * 组装类库文件地址
     * 
     * @static
     *
     * @access public
     * @param string $class 类名
     * @return string 返回组装的类文件地址
     */
    public static function findFile($class)
    {
        if (isset(ClassAlias::getClass($class))) {
            // 类库映射指向
            $classFile = ClassAlias::getClass($class);
        } elseif (SpaceAlias::getSpace($class)) {
            // 命名空间指向
            $classFile = SpaceAlias::getSpace($class) . 'php';
        } else { // 默认指向到框架框架
            $classFile = DREAM_PATH . DS . $class . 'php';
        }
        
        return $classFile;
    }

    /**
     * 装载类文件
     * 
     * @static
     *
     * @access protected
     * @param string $file 类文件
     * @return boolean 成功返回 “true”，否则返回 “false”
     */
    protected static function load($file)
    {
        if (is_file($file)) { // 类文件存在，装载类文件
            return (require $file) ? TRUE : FALSE;
        }
    }

    /**
     * 初始化类
     * 
     * @static
     *
     * @access protected
     * @param string $class 类名
     * @return void 没有返回值
     */
    protected static function initclass($class)
    {
        if (method_exists($class, '_init')) { // 初始化类
            call_user_func([
                $class,
                '_init'
            ]);
        }
    }

    /**
     * 导入类库文件 该方法不建议使用，在后续版本中有可能会被移除
     * 
     * @static
     *
     * @access public
     * @param string $file 类库文件地址
     * @return boolean 类库加载成功返回 “true”，否则返回 “false”
     */
    public function import($file)
    {
        if (! isset(self::$loadFileList[$file])) { // 类文件没有装载过
            if (isset(ClassAlias::getClass($file))) {
                // 类库映射指向
                $classFile = ClassAlias::getClass($file);
            } elseif (PathAlias::getPath($file)) {
                $classFile = PathAlias::getPath($file);
            } else {
                $classFile = realpath($file . 'php');
            }
            if (self::load($classFile)) { // 类文件引入成功
                unset($classFile);
                
                return TRUE;
            }
        }
        
        return FALSE;
    }
}